package com.hontech.bvapp2.ui.parts.setting

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.FrameLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexWrap
import com.google.android.flexbox.FlexboxLayoutManager
import com.hontech.bvapp2.R
import com.hontech.bvapp2.device.Address
import com.hontech.bvapp2.device.Back
import com.hontech.bvapp2.device.cp.Cargo
import com.hontech.bvapp2.device.cp.Door
import com.hontech.bvapp2.device.cp.Drop
import com.hontech.bvapp2.device.cp.Heat
import com.hontech.bvapp2.service.FirmFile
import com.hontech.bvapp2.service.TbFirmFile
import com.hontech.bvapp2.ui.dialog.runProg
import com.hontech.bvapp2.ui.view.LabelSpinner
import com.hontech.bvapp2.ui.view.LabelTextView
import com.hontech.bvapp2.utils.AppTask
import com.hontech.bvapp2.utils.Version
import com.hontech.bvapp2.utils.installApk2
import com.hontech.bvapp2.utils.onClick
import com.hontech.bvapp2.utils.registerEvent
import com.hontech.bvapp2.utils.runNewThread
import com.hontech.bvapp2.utils.unregister
import kotlinx.coroutines.delay
import okhttp3.internal.format
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

private const val TYPE_IPC = 1L
private const val TYPE_CARGO1 = 32L
private const val TYPE_CARGO2 = 35L
private const val TYPE_HEAT = 38L
private const val TYPE_DOOR = 41L
private const val TYPE_DROP = 44L

class OtaParts (context: Context, attrs: AttributeSet) : FrameLayout(context, attrs) {

    private val ltIpc: LabelTextView
    private val ltDrop: LabelTextView
    private val ltCargo1: LabelTextView
    private val ltCargo2: LabelTextView
    private val ltHeat: LabelTextView
    private val ltDoor: LabelTextView

    private val spType: LabelSpinner
    private val btnGetUpdate: Button
    private val rv: RecyclerView

    init {
        val view = LayoutInflater.from(context).inflate(R.layout.parts_setting_ota, this)

        ltIpc = view.findViewById(R.id.id_ota_lt_ipc)
        ltDrop = view.findViewById(R.id.id_ota_lt_drop)
        ltCargo1 = view.findViewById(R.id.id_ota_lt_cargo1)
        ltCargo2 = view.findViewById(R.id.id_ota_lt_cargo2)
        ltHeat = view.findViewById(R.id.id_ota_lt_heat)
        ltDoor = view.findViewById(R.id.id_ota_lt_door)
        spType = view.findViewById(R.id.id_ota_sp_type)
        btnGetUpdate = view.findViewById(R.id.id_ota_btn_ota_update)
        rv = view.findViewById(R.id.id_ota_rv)

        rv.layoutManager = FlexboxLayoutManager(context, FlexDirection.ROW, FlexWrap.WRAP)

        /**
         *         <item>工控机</item>
         *         <item>切膜落杯控制板</item>
         *         <item>货架1控制板</item>
         *         <item>货架2控制板</item>
         *         <item>加热控制板</item>
         *         <item>门控制板</item>
         */
        btnGetUpdate.onClick { onClickUpdate() }

        AppTask.run {
            ltIpc.set(Version)
        }
    }

    override fun onWindowVisibilityChanged(visibility: Int) {
        super.onWindowVisibilityChanged(visibility)
        if (visibility == VISIBLE) {
            registerEvent(this)
        } else {
            unregister(this)
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onHeatStatus(status: Heat.Status) {
        ltHeat.set(status.version())
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onDropStatus(status: Drop.Status) {
        ltDrop.set(status.version())
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onCargoStatus(status: Cargo.Status) {
        if (status.cargoId == 1) {
            ltCargo1.set(status.version())
        } else if (status.cargoId == 2) {
            ltCargo2.set(status.version())
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onDoorStatus(status: Door.Status) {
        ltDoor.set(status.version())
    }

    private suspend fun onClickUpdate() {
        runProg("获取更新", "") {
            val name = spType.selectText()
            val type = when (name) {
                "工控机" -> TYPE_IPC
                "切膜落杯控制板" -> TYPE_DROP
                "货架1控制板" -> TYPE_CARGO1
                "货架2控制板" -> TYPE_CARGO2
                "加热控制板" -> TYPE_HEAT
                "门控制板" -> TYPE_DOOR
                else -> throw IllegalStateException("无效的控制板")
            }
            val fs = FirmFile.query(type)
            rv.adapter = Adapter(type, fs)
        }
    }

}

private fun sizeStr(size: Long): String {
    return if (size < 1024) {
        "${size}Byte"
    } else if (size < (1024 * 1024)) {
        val n = size.toDouble()
        format("%.2fKB", n / 1024)
    } else if (size < (1024 * 1024 * 1024)) {
        val n = size.toDouble()
        format("%.2fMB", n / 1024 / 1024)
    } else {
        val n = size.toDouble()
        format("%.2fGB", n / 1024 / 1024 / 1024)
    }
}

private class Item(view: View) : RecyclerView.ViewHolder(view) {

    private val ltVersion = view.findViewById<LabelTextView>(R.id.id_item_ota_lt_version)
    private val ltDate = view.findViewById<LabelTextView>(R.id.id_item_ota_lt_date)
    private val ltSize = view.findViewById<LabelTextView>(R.id.id_item_ota_lt_size)
    private val ltDescribe = view.findViewById<LabelTextView>(R.id.id_item_ota_lt_describe)
    private val btnUpdate = view.findViewById<Button>(R.id.id_item_btn_update)

    private suspend fun updateMCU(id: Long, dst: Int) {
        val cpName = Address.getName(dst)
        runProg(cpName, "更新") { dialog ->
            val buf = FirmFile.downloadBin(id)
            dialog.setMsg("下载成功开始更新")
            Back.ota(buf, dst) {
                dialog.setMsg("进度:${it}%")
            }
        }
    }


    private suspend fun updateApp(id: Long) {
        runProg("APP更新", "更新") { dialog ->
            val path = FirmFile.downloadApk(id) {
                dialog.setMsg("下载进度:${it}%")
            }
            delay(100)
            dialog.setMsg("更新成功 开始安装")
            runNewThread { installApk2(path) }
        }
    }


    fun setUp(file: TbFirmFile, type: Long) {
        ltVersion.set(file.version)
        ltDate.set(file.dateFormat())
        ltSize.set(sizeStr(file.size))
        ltDescribe.set(file.description)
        btnUpdate.onClick {
            if (type == TYPE_IPC) {
                updateApp(file.id)
            } else {
                val dst = when (type) {
                    TYPE_DOOR -> Address.DOOR
                    TYPE_HEAT -> Address.HEAT
                    TYPE_CARGO1 -> Address.CARGO1
                    TYPE_CARGO2 -> Address.CARGO2
                    TYPE_DROP -> Address.DROP
                    else -> throw IllegalStateException("无效的类型:$type")
                }
                updateMCU(file.id, dst)
            }
        }
    }
}

private class Adapter(val type: Long, val result: Array<TbFirmFile>) :
    RecyclerView.Adapter<Item>() {

    override fun getItemCount(): Int {
        return result.size
    }

    override fun onBindViewHolder(holder: Item, position: Int) {
        val file = result[position]
        holder.setUp(file, type)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Item {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_ota_info, parent, false)
        return Item(view)
    }
}
























